package com.songlanyun.modules.article.service.impl;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.enums.ArticleConstant;
import com.songlanyun.common.enums.IntegralConstant;
import com.songlanyun.common.enums.OpusConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.BeanUtil;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;
import com.songlanyun.common.utils.RedisKeys;
import com.songlanyun.modules.account.service.UserInfoService;
import com.songlanyun.modules.apphome.service.HomePageService;
import com.songlanyun.modules.article.dao.ArticleDao;
import com.songlanyun.modules.article.entity.Article;
import com.songlanyun.modules.article.model.dto.ArticleDTO;
import com.songlanyun.modules.article.model.vo.ArticleVO;
import com.songlanyun.modules.article.service.ArticleContentService;
import com.songlanyun.modules.article.service.ArticleCourseService;
import com.songlanyun.modules.article.service.ArticleService;
import com.songlanyun.modules.comment.entity.UserComment;
import com.songlanyun.modules.comment.service.UserCommentService;
import com.songlanyun.modules.exception.BbsException;
import com.songlanyun.modules.integralconfig.entity.IntegralConfig;
import com.songlanyun.modules.integralconfig.service.IntegralConfigService;
import com.songlanyun.modules.integralrecord.entity.IntegralRecord;
import com.songlanyun.modules.integralrecord.service.IntegralRecordService;
import com.songlanyun.modules.like.service.LikeRecordService;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service("articleService")
public class ArticleServiceImpl extends ServiceImpl<ArticleDao, Article> implements ArticleService {

    @Resource
    private ArticleContentService articleContentService;
    @Resource
    private ArticleCourseService articleCourseService;

    @Resource
    private UserCommentService userCommentService;
    @Resource
    private IntegralRecordService integralRecordService;
    @Resource
    private IntegralConfigService integralConfigService;
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private LikeRecordService likeRecordService;
    @Resource
    private HomePageService homePageService;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
//        IPage<Article> page = this.baseMapper.articlePage(new Query<Article>().getPage(params), params);

        String title = MapUtil.getStr(params, "title");
        IPage<Article> page = this.page(
                new Query<Article>().getPage(params),
                new LambdaQueryWrapper<Article>()
                        .like(StringUtils.isNotBlank(title), Article::getTitle, title)
                        .orderByDesc(Article::getCreateTime)
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void saveArticle(ArticleDTO dto, Long userId) {
        //保存文章
        Article article = new Article();
        BeanUtil.copyPropertiesIgnoreNull(dto, article);
        article.setCreator(userId);
        article.setArticleType(ArticleConstant.ArticleType.getByCode(dto.getArticleType()));
        article.initSum();
        this.baseMapper.insert(article);

        //保存文章内容
        articleContentService.saveContent(article.getId(), dto);

        //保存文章课程分类
        articleCourseService.saveArticleCourse(article.getId(), dto.getCourseId());

    }

    @Override
    @Transactional
    public void updateArticle(ArticleDTO dto) {
        //更新文章
        Article article = this.getById(dto.getId(), true);
        //更新初始化总数
        article.updateInitSum(dto);

        BeanUtil.copyPropertiesIgnoreNull(dto, article);
        article.setArticleType(ArticleConstant.ArticleType.getByCode(dto.getArticleType()));
        this.baseMapper.updateById(article);

        //更新文章内容
        articleContentService.updateContent(article.getId(), dto);

        //更新文章课程分类
        articleCourseService.updateArticleCourse(article.getId(), dto.getCourseId());
    }

    @Override
    public Article getById(Long aid, boolean isThrow) {
        Article article = this.baseMapper.selectById(aid);
        if (article == null && isThrow) {
            throw new RRException(BbsException.ARTICLE_NOT_EXIST);
        }
        return article;
    }

    @Override
    public void setRecommend(Long aid, Boolean isRecommend) {
        this.update(
                new LambdaUpdateWrapper<Article>()
                        .eq(Article::getId, aid)
                        .set(Article::getIsRecommend, isRecommend)
        );
    }

    @Override
    public ArticleVO info(Long id) {
        ArticleVO info = this.baseMapper.info(id);
        info.loadContent();
        return info;
    }

    @Override
    public PageUtils appList(Map<String, Object> params) {
        IPage<Article> page = this.baseMapper.articleAppPage(new Query<Article>().getPage(params), params);
        page.getRecords().forEach(o -> {
            o.setLikeNum(likeRecordService.likeSum(OpusConstant.ModelType.ARTICLE, o.getId()));
        });
        return new PageUtils(page);
    }

    @Override
    public PageUtils recommendList(Map<String, Object> params) {
        params.put("recommend", 1);//推荐
        return this.appList(params);
    }

    @Override
    public PageUtils hotList(Map<String, Object> params) {
        params.put("hot", 1);
        return this.appList(params);
    }

    @SuppressWarnings("unchecked")
    private List<Article> list(Map<String, Object> params) {
        Integer recommend = MapUtil.getInt(params, "recommend");
        Integer hot = MapUtil.getInt(params, "hot");
        String title = MapUtil.getStr(params, "title");

        return this.baseMapper.selectList(
                new LambdaQueryWrapper<Article>()
                        .eq(Article::getAdded, true)
                        .eq(recommend != null, Article::getIsRecommend, recommend)
                        .like(StringUtils.isNotBlank(title), Article::getTitle, title)
                        .orderByDesc(hot != null, Article::getLikeNum)
                        .orderByDesc(Article::getCreateTime)
        );
    }


    @Override
    public Boolean ifCreateArticle(Long cid) {
        return this.baseMapper.ifCreateArticle(cid);
    }

    @Override
    @Transactional
    public void del(Long id) {
        //删除文章
        this.baseMapper.deleteById(id);
        //删除文章内容
        articleContentService.removeByAid(id);
        //删除文章关联
        articleCourseService.removeByAid(id);

        //删除浏览、点赞、分享、评论等记录
        homePageService.delRecord(OpusConstant.ModelType.ARTICLE, id);

    }

    @Override
    public void added(Long aid, Boolean added) {
        this.update(
                new LambdaUpdateWrapper<Article>()
                        .eq(Article::getId, aid)
                        .set(Article::getAdded, added)
        );
    }

    @Override
    public ArticleVO appInfo(Long userId, Long id) {
        ArticleVO info = this.baseMapper.info(id);
        info.loadContent();
        info.loadUserCommentList();//所有评论
        info.loadIsLike(userId);//是否点赞
        return info;
    }

    @Override
    public void comment(UserComment userComment) {

        Article article = this.getById(userComment.getModelId(), true);
        //根据opusId、userId、去查询评论表记录，看是否增加评论人数记录
        Boolean comment = userCommentService.comment(userComment);
        //是否有效  有效评论才进行下面操作
        if (userComment.getIsShow()) {
            //增加评论总数
            article.addCommentSum(1);
            if (comment) {
                //增加作品评论人数
                article.addCommentNum(1);
            }
            //是否已赠送积分
            Boolean exists = integralRecordService.exists(OpusConstant.ModelType.ARTICLE, article.getId(),
                    userComment.getCommentUserId(), IntegralConstant.InnerMode.COMMENT);
            if (!exists) {
                IntegralConfig config = integralConfigService.get();
                if (config != null) {
                    //评论人获得积分
                    String name = userInfoService.getNameById(userComment.getCommentUserId());
                    IntegralRecord record = new IntegralRecord(userComment.getCommentUserId(), config.getComment(), IntegralConstant.InnerMode.COMMENT,
                            IntegralConstant.IntegralModelType.ARTICLE, userComment.getId(), "评论文章获得积分");
                    record.setRemark(String.format("会员【%s】评论文章【%s】获得积分:%s", name, article.getTitle(), record.getValue()));
                    integralRecordService.inner(record);
                }
            }
        }

    }

    @Override
    @Transactional
    public Map<String, Object> cancelLike(Long id, Long userId) {
        Map<String, Object> map = new HashMap<>();

        Article article = this.getById(id, true);
        //删除redis缓存
        Boolean delLikeRedis = likeRecordService.delLikeRedis(userId, RedisKeys.BbsKey.LIKE_ARTICLE_KEY, article.getId());

        //删除会员对作品的点赞记录
        if (!delLikeRedis && likeRecordService.isLike(userId, OpusConstant.ModelType.ARTICLE, id)) {
            likeRecordService.delLike(userId, OpusConstant.ModelType.ARTICLE, id);
            //减少作品点赞人数
            article.subLikeNum(1);
        }

        map.put("is_like", false);
        map.put("like_num", article.getLikeNum());
        return map;
    }

}
